﻿using System;

namespace Innovative.ProXr
{
	public static partial class DirectApi
	{
		/// <summary>
		/// The ProXR Series controllers have 16 user-programmable timers. Each independent timer can be assigned to 
		/// any of the first 256 relays of the ProXR controller. Timers may be programmed to hold the relay in the 
		/// On state, or to pulse the relay at the end of the timer. The ProXR timing features are ideally suited 
		/// for Watchdog, Keep Alive, and Server Reboot applications, as well as sprinkler systems, gate openers, 
		/// and day/night lighting applications.
		/// Timer commands allow you to set a time that counts down to either active a relay or to pulse a relay. Once you have sent
		/// a simple timer command, the timer automatically starts counting down. There are two types of simple timers: Duration and Pulse
		/// </summary>
		public static class Timers
		{
			/// <summary>
			/// Activates a duration or pulse timer specified in the parameters using the given TimeSpan value as the trigger.
			/// </summary>
			public static RelayCommandSet<bool, RelayTimer, TimeSpan, int> ActivateTimer = new RelayCommandSet<bool, RelayTimer, TimeSpan, int>()
			{
				Commands = new RelayCommand[]
				{
					RelayCommand.Command254,
					RelayCommand.CreateReadOnlyCommand(1, 50, "TimerSetup"),
					RelayCommand.CreateNonOptionalParameterCommand(2,(new RelayByte[0]).CreateRange(50, 65).AppendBytes((new RelayByte[0]).CreateRange(70, 85)).AppendBytes((new RelayByte[0]).CreateRange(90, 105)).AppendBytes((new RelayByte[0]).CreateRange(110, 125)) , "Timer"),
					RelayCommand.CreateNonOptionalParameterCommand(3, (new RelayByte[0]).CreateRange(0, 255), "Hours"),
					RelayCommand.CreateNonOptionalParameterCommand(4, (new RelayByte[0]).CreateRange(0, 255), "Minutes"),
					RelayCommand.CreateNonOptionalParameterCommand(5, (new RelayByte[0]).CreateRange(0, 255), "Seconds"),
					RelayCommand.CreateNonOptionalParameterCommand(6, (new RelayByte[0]).CreateRange(0, 255), "Relay"),

				},
				ExpectedResults = new RelayByte[] { 85 },
				ResponseConverter = new Boolean85ResponseConverter(),
				Parameter1Converter = new TimerParameterConverter(),
				Parameter2Converter = new TimeSpanParameterConverter(),
				Parameter3Converter = new Int32ParameterConverter()
			};

			/// <summary>
			/// This command will query the time remaining for the selected timer 1 through 16. This command reports 4 bytes 
			/// back to the user, indicating Hours remaining (0-255), Minutes remaining (0-255), Seconds remaining (0-255), 
			/// and the Relay Number the timer is assigned to (0-255).
			/// </summary>
			public static RelayCommandSet<TimeSpan, int> QueryRemainingTime = new RelayCommandSet<TimeSpan, int>()
			{
				Commands = new RelayCommand[]
				{
					RelayCommand.Command254,
					RelayCommand.CreateReadOnlyCommand(1, 50, "TimerSetup"),
					RelayCommand.CreateReadOnlyCommand(2, 130),
					RelayCommand.CreateNonOptionalParameterCommand(3, (new RelayByte[0]).CreateRange(1, 16), "Timer")

				},
				ExpectedResults = (new RelayByte[0]).CreateRange(0, 255),
				ResponseConverter = new TimeSpanResponseConverter(),
				Parameter1Converter = new Int32ParameterConverter()
			};

			/// <summary>
			/// This command is used to manually halt or resume all 16 timers. This command works with all forms of timers. The 
			/// LSB and MSB are the least significant and most significant bytes in a 16-bit word. The status of each bit 
			/// within the 16-bit word is used to control which timers are running. Every bit that is high in the word 
			/// indicates the timer is active. Every bit that is low in the word indicates the timer is not running.
			/// </summary>
			public static RelayCommandSet<bool, ActivateTimers> HaltOrResume = new RelayCommandSet<bool, ActivateTimers>()
			{
				Commands = new RelayCommand[]
				{
					RelayCommand.Command254,
					RelayCommand.CreateReadOnlyCommand(1, 50, "TimerSetup"),
					RelayCommand.CreateReadOnlyCommand(2, 131),
					RelayCommand.CreateNonOptionalParameterCommand(3, (new RelayByte[0]).CreateRange(0, 255), "LSB"),
					RelayCommand.CreateNonOptionalParameterCommand(4, (new RelayByte[0]).CreateRange(0, 255), "MSB")
				},
				ExpectedResults = new RelayByte[] { 85 },
				ResponseConverter = new Boolean85ResponseConverter(),
				Parameter1Converter = new ActivateTimerParameterConverter()
			};

			/// <summary>
			/// This command will calibrate the relay timer. The LSB and MSB make up a word, indicating the speed of the 
			/// timer. Lower values indicate a faster timer while higher values indicates a slower timer. This command 
			/// no-longer stores the calibration data into the controller. Use device configuration to store a new 
			/// calibration value. This command is valuable for experimenting with other calibration values.
			/// </summary>
			public static RelayCommandSet<bool, short> CalibrateRelayTimer = new RelayCommandSet<bool, short>()
			{
				Commands = new RelayCommand[]
				{
					RelayCommand.Command254,
					RelayCommand.CreateReadOnlyCommand(1, 50, "TimerSetup"),
					RelayCommand.CreateReadOnlyCommand(2, 132),
					RelayCommand.CreateNonOptionalParameterCommand(3, (new RelayByte[0]).CreateRange(0, 255), "LSB"),
					RelayCommand.CreateNonOptionalParameterCommand(4, (new RelayByte[0]).CreateRange(0, 255), "MSB")
				},
				ExpectedResults = new RelayByte[] { 85 },
				ResponseConverter = new Boolean85ResponseConverter(),
				Parameter1Converter = new WordParameterConverter()
			};

			/// <summary>
			/// This command retrieves the Timer Calibration Value. The Timer Calibration Value controls the actual 
			/// length of a se-cond. Two bytes will be returned by this command, LSB and MSB. The Word value of the 
			/// timer = LSB + (MSB*256) Decreasing this value will speed up the timer, increasing this value will 
			/// slow it down. Use device configuration commands 254,53 and 254,54 to store and retrieve 
			/// these data out of EEPROM.
			/// </summary>
			public static RelayCommandSet<short> RetrieveTimerCalibration = new RelayCommandSet<short>()
			{
				Commands = new RelayCommand[]
				{
					RelayCommand.Command254,
					RelayCommand.CreateReadOnlyCommand(1, 50, "TimerSetup"),
					RelayCommand.CreateReadOnlyCommand(2, 133)
				},
				ExpectedResults = (new RelayByte[0]).CreateRange(0, 255),
				ResponseConverter = new WordResponseConverter()
			};

			/// <summary>
			/// This command turns on the timing calibration markers. This command is not generally used by 
			/// software developers, but is used by Base application software to help the user measure the
			/// elapsed time of the timer values.
			/// </summary>
			public static RelayCommandSet TurnTimingCalibrationMarkersOn = new RelayCommandSet()
			{
				Commands = new RelayCommand[]
				{
					RelayCommand.Command254,
					RelayCommand.CreateReadOnlyCommand(1, 50, "TimerSetup"),
					RelayCommand.CreateReadOnlyCommand(2, 134)
				},
				ExpectedResults = new RelayByte[] { 85, 90, 91 }
			};

			/// <summary>
			/// This command turns off the timing calibration markers. This command is not generally used by 
			/// software developers, but is used by Base application software to help the user measure the 
			/// elapsed time of the timer values.
			/// </summary>
			public static RelayCommandSet<bool> TurnTimingCalibrationMarkersOff = new RelayCommandSet<bool>()
			{
				Commands = new RelayCommand[]
				{
					RelayCommand.Command254,
					RelayCommand.CreateReadOnlyCommand(1, 50, "TimerSetup"),
					RelayCommand.CreateReadOnlyCommand(2, 135)
				},
				ExpectedResults = new RelayByte[] { 85 },
				ResponseConverter = new Boolean85ResponseConverter()
			};
		}
	}
}
